package datenverwaltung;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.jdesktop.xswingx.PromptSupport;

import com.main.meldungsverwaltung.GUI;

public class TrackerDownloadThread extends Thread implements DBVerbindung {

	private GUI container;
	private JProgressBar bar;
	private JTable tabelle;
	private Map<String, Tracker> trackerListe = new HashMap<String, Tracker>();
	private ArrayList<Tracker> list;
	private static final String[] columnNames = { "ID", "Zuverl.",
			"Anz. Meldungen", "Aktiv-Ang.", "Inaktiv-Ang.",
			"Gesamt Anz. Angaben", "Nachname", "Vorname", "E-Mail", "Wohnort",
			"PLZ", "Straße", "Tel" };

	public TrackerDownloadThread(GUI container, JProgressBar bar) {
		super();
		this.container = container;
		this.bar = bar;
	}

	@Override
	public Connection getConnection() throws Exception {
		Connection connection;
		Class.forName("com.mysql.jdbc.Driver");
		connection = DriverManager.getConnection(DB_CONNECTION_URL,
				DB_USERNAME, DB_PASSWORD);
		return connection;
	}

	@Override
	public ResultSet executeStatementOnDB(String select) throws Exception {
		Connection connection = getConnection();
		Statement statement = connection.createStatement();
		ResultSet result = statement.executeQuery(select);
		return result;
	}

	@Override
	public void run() {
		try {
			getTrackers();
			leseZusatzInformationen();
			createTrackerDialog();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		bar.setIndeterminate(false);
		container.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
	}

	/**
	 * Füllt die Tracker-Liste mit den Trackern.
	 * 
	 * @throws Exception
	 */
	public void getTrackers() throws Exception {
		String select = "select tracker.id,tracker.passwort,tracker.zuverlaessigkeit,count(meldung.id) anzahlM,ifnull(sum(meldung.anzAktiv),0) aktivA,ifnull(sum(meldung.anzInaktiv),0) inaktivA from tracker left outer join meldung on tracker.id=meldung.tracker_id group by tracker.id;";
		ResultSet result = executeStatementOnDB(select);
		while (result.next()) {
			trackerListe.put(
					result.getString("id"),
					new Tracker(result.getString("id"), Float.parseFloat(result
							.getString("zuverlaessigkeit")), Integer
							.parseInt(result.getString("anzahlM")), Integer
							.parseInt(result.getString("aktivA")), Integer
							.parseInt(result.getString("inaktivA")), Integer
							.parseInt(result.getString("aktivA"))
							+ Integer.parseInt(result.getString("inaktivA"))));
		}
	}

	/**
	 * Füllt die restlichen Tracker-Attribute der Tracker in der Liste.
	 */
	private void leseZusatzInformationen() {
		try {
			JAXBContext context = JAXBContext.newInstance(TrackerList.class);
			Unmarshaller unmarshaller = context.createUnmarshaller();
			File file = new File(GUI.XML_FILENAME);
			if (!file.exists())
				try {
					file.createNewFile();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			TrackerList liste = (TrackerList) unmarshaller
					.unmarshal(new FileReader(file));
			// Durch Tracker in der Datei gehen
			for (String key : trackerListe.keySet())
				if (liste.trackerListe.containsKey(key)) {
					Tracker t = trackerListe.get(key);
					Tracker temp = liste.trackerListe.get(key);
					t.setEmail(temp.getEmail());
					t.setTel(temp.getTel());
					t.setVorname(temp.getVorname());
					t.setNachname(temp.getNachname());
					t.setAdresse(new Adresse(temp.getAdresse().getWohnort(),
							temp.getAdresse().getStrasse(), temp.getAdresse()
									.getPlz()));
				}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JAXBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Erstellt einen Dialog zum Anzeigen der Tracker-Liste.
	 */
	private void createTrackerDialog() {
		final JFrame dialog = new JFrame();
		dialog.setBounds(container.getX() + 50, container.getY() + 20, 1200,
				600);
		dialog.setLayout(new BorderLayout());

		tabelle = new JTable();
		tabelle.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		final TableModel model = createTableModel();
		tabelle.setModel(model);

		TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(
				model);
		Comparator<String> comp = new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				try {
					long z1 = Long.parseLong(o1);
					long z2 = Long.parseLong(o2);
					return (int) (z1 - z2);
				} catch (NumberFormatException e) {
				}
				try {
					float z1 = Float.parseFloat(o1);
					float z2 = Float.parseFloat(o2);
					return (int) (z1 * 100000 - z2 * 100000);
				} catch (NumberFormatException e) {
				}
				return o1.compareTo(o2);
			}
		};
		for (int i = 0; i < tabelle.getColumnCount(); i++)
			sorter.setComparator(i, comp);
		tabelle.setRowSorter(sorter);

		JMenuBar menuBar = new JMenuBar();
		menuBar.setLayout(new GridLayout(1, 2));
		JPanel suchPanel = new JPanel();
		suchPanel.setBackground(Color.GRAY);
		JButton weiterSuchen = new JButton("weitersuchen");
		weiterSuchen.setBackground(Color.GRAY);
		final JLabel suchStatus = new JLabel("Suchstatus: ");
		suchStatus.setForeground(Color.WHITE);
		final JTextField suchFeld = new JTextField();
		suchPanel.add(suchFeld);
		suchPanel.add(weiterSuchen);
		suchPanel.add(suchStatus);
		PromptSupport.setPrompt("Suchen", suchFeld);

		JPanel tPanel = new JPanel();
		tPanel.setBackground(Color.GRAY);
		JButton tLöschen = new JButton("Trucker löschen");
		tLöschen.setBackground(Color.GRAY);
		final JProgressBar tBar = new JProgressBar();
		tLöschen.setToolTipText("Löscht den in gewählten Trucker und all seine Meldungen komplett aus der Datenbank!");
		tPanel.add(tLöschen);
		tPanel.add(tBar);

		suchFeld.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				if (markiereGesuchtenEintrag(suchFeld.getText(), 0)) {
					suchStatus.setText("Suchstatus: Gefunden!");
					suchStatus.setForeground(Color.GREEN);
				} else {
					suchStatus.setText("Suchstatus: Wort nicht vorhanden!");
					suchStatus.setForeground(Color.RED);
				}
			}
		});

		weiterSuchen.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				if (markiereGesuchtenEintrag(suchFeld.getText(), tabelle
						.convertRowIndexToModel(tabelle.getSelectedRow()) + 1)) {
					suchStatus.setText("Suchstatus: Gefunden!");
					suchStatus.setForeground(Color.GREEN);
				} else {
					suchStatus
							.setText("Suchstatus: Nicht gefunden, Tabellenende erreicht!");
					suchStatus.setForeground(Color.ORANGE);
				}

			}
		});

		tLöschen.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				if (JOptionPane
						.showConfirmDialog(
								dialog,
								"Achtung! Damit wird der Trucker ("
										+ list.get(
												tabelle.convertRowIndexToModel(tabelle
														.getSelectedRow()))
												.getId()
										+ ") und all seine Meldungen endgültig aus der Datenbank gelöscht!",
								"Achtung!", JOptionPane.OK_CANCEL_OPTION,
								JOptionPane.WARNING_MESSAGE) == 0) {
					int selectedRow = tabelle.convertRowIndexToModel(tabelle
							.getSelectedRow());
					String id = list.get(selectedRow).getId();
					list.remove(selectedRow);
					trackerListe.remove(id);
					// try {
					// tabelle.setRowSelectionInterval(selectedRow + 1,
					// selectedRow + 1);
					// } catch (IllegalArgumentException e1) {
					// tabelle.setRowSelectionInterval(0, 0);
					// }
					tabelle.repaint();
					TrackerVerwaltenThread tvt = new TrackerVerwaltenThread(
							TrackerVerwaltungAction.TRACKER_LÖSCHEN, tBar, id,
							dialog);
					tBar.setIndeterminate(true);
					dialog.setCursor(Cursor
							.getPredefinedCursor(Cursor.WAIT_CURSOR));
					tvt.start();
				}
			}
		});

		menuBar.add(suchPanel);
		menuBar.add(tPanel);

		dialog.add(new JScrollPane(tabelle), BorderLayout.CENTER);
		dialog.add(menuBar, BorderLayout.SOUTH);

		suchFeld.setPreferredSize(new Dimension(150, 25));
		dialog.setVisible(true);
	}

	private TableModel createTableModel() {
		list = new ArrayList<Tracker>(trackerListe.values());
		Collections.sort(list);
		TableModel model = new TableModel() {

			@Override
			public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
				// TODO Auto-generated method stub

			}

			@Override
			public void removeTableModelListener(TableModelListener l) {
				// TODO Auto-generated method stub

			}

			@Override
			public boolean isCellEditable(int rowIndex, int columnIndex) {
				// TODO Auto-generated method stub
				return false;
			}

			@Override
			public Object getValueAt(int rowIndex, int columnIndex) {
				return list.get(rowIndex).get(columnIndex);
			}

			@Override
			public int getRowCount() {
				return list.size();
			}

			@Override
			public String getColumnName(int columnIndex) {
				return columnNames[columnIndex];
			}

			@Override
			public int getColumnCount() {
				return columnNames.length;
			}

			@Override
			public Class<?> getColumnClass(int columnIndex) {
				return String.class;
			}

			@Override
			public void addTableModelListener(TableModelListener l) {
				// TODO Auto-generated method stub

			}
		};
		return model;
	}

	private boolean markiereGesuchtenEintrag(String suche, int suchBeginn) {
		for (int i = suchBeginn; i < list.size(); i++) {
			Tracker t = list.get(i);
			if (t.toString().toLowerCase().contains(suche.toLowerCase())) {
				tabelle.setRowSelectionInterval(
						tabelle.convertRowIndexToView(i),
						tabelle.convertRowIndexToView(i));
				tabelle.scrollRectToVisible(tabelle.getCellRect(
						tabelle.convertRowIndexToView(i), 0, true));
				return true;
			}
		}
		return false;
	}

}
